#!/bin/bash
# Copyright (c) 2025 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


set -eu
set -o pipefail

# Global variables
SOURCES_LIST="/etc/apt/sources.list"
BACKUP_FILE="/etc/apt/sources.list.backup"

# Constants for pip configuration
PIP_CONFIG_DIR="$HOME/.pip"
PIP_CONFIG_FILE="$PIP_CONFIG_DIR/pip.conf"
PIP_CONFIG_BACKUP="$PIP_CONFIG_DIR/pip.conf.backup"

# Logging function
log() {
    local level=$1
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
}

# Check if root
check_root() {
    if [ "$EUID" -ne 0 ]; then
        log "ERROR" "This script must be run as root (using sudo)"
        exit 1
    fi
    log "INFO" "Root privileges verified"
}

# Create backup of sources.list
backup_sources() {
    if [ -f "$SOURCES_LIST" ]; then
        cp "$SOURCES_LIST" "$BACKUP_FILE"
        if [ $? -eq 0 ]; then
            log "INFO" "Successfully backed up $SOURCES_LIST to $BACKUP_FILE"
        else
            log "ERROR" "Failed to create backup of $SOURCES_LIST"
            exit 1
        fi
    else
        log "ERROR" "Sources list file not found at $SOURCES_LIST"
        exit 1
    fi
}

# Detect distribution and codename
detect_distribution() {
    if [ -f /etc/lsb-release ]; then
        . /etc/lsb-release
        DISTRO_CODENAME=$DISTRIB_CODENAME
        DISTRO_TYPE="ubuntu"
    elif [ -f /etc/os-release ]; then
        . /etc/os-release
        DISTRO_CODENAME=$VERSION_CODENAME
        if [[ "$ID" == "debian" ]]; then
            DISTRO_TYPE="debian"
        else
            DISTRO_TYPE="ubuntu"
        fi
    else
        log "ERROR" "Could not determine distribution version"
        exit 1
    fi
    log "INFO" "Detected distribution: $DISTRO_TYPE ($DISTRO_CODENAME)"
}

# Generate sources.list content based on distribution
generate_sources_content() {
    if [[ "$DISTRO_TYPE" == "ubuntu" ]]; then
        cat > "$SOURCES_LIST" << EOF
# Tsinghua University Mirror for Ubuntu
# Generated on $(date)
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME} main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME}-updates main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME}-backports main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME}-security main restricted universe multiverse

# Source repositories
# deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME} main restricted universe multiverse
# deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME}-updates main restricted universe multiverse
# deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME}-backports main restricted universe multiverse
# deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ${DISTRO_CODENAME}-security main restricted universe multiverse
EOF
    elif [[ "$DISTRO_TYPE" == "debian" ]]; then
        cat > "$SOURCES_LIST" << EOF
# Tsinghua University Mirror for Debian
# Generated on $(date)
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ ${DISTRO_CODENAME} main contrib non-free
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ ${DISTRO_CODENAME}-updates main contrib non-free
deb http://mirrors.tuna.tsinghua.edu.cn/debian-security ${DISTRO_CODENAME}-security main contrib non-free

# Source repositories
# deb-src http://mirrors.tuna.tsinghua.edu.cn/debian/ ${DISTRO_CODENAME} main contrib non-free
# deb-src http://mirrors.tuna.tsinghua.edu.cn/debian/ ${DISTRO_CODENAME}-updates main contrib non-free
# deb-src http://mirrors.tuna.tsinghua.edu.cn/debian-security ${DISTRO_CODENAME}-security main contrib non-free
EOF
    fi

    if [ $? -eq 0 ]; then
        log "INFO" "Successfully generated new sources.list"
    else
        log "ERROR" "Failed to generate new sources.list"
        exit 1
    fi
}

# Cleanup function
cleanup() {
    if [ $? -ne 0 ]; then
        log "ERROR" "Script failed with exit code $?"
    fi
}

# Create pip config directory if it doesn't exist
setup_pip_directory() {
    if [ ! -d "$PIP_CONFIG_DIR" ]; then
        mkdir -p "$PIP_CONFIG_DIR"
        if [ $? -eq 0 ]; then
            log "INFO" "Created pip config directory at $PIP_CONFIG_DIR"
        else
            log "ERROR" "Failed to create pip config directory"
            return 1
        fi
    fi
    return 0
}

# Backup existing pip configuration
backup_pip_config() {
    if [ -f "$PIP_CONFIG_FILE" ]; then
        cp "$PIP_CONFIG_FILE" "$PIP_CONFIG_BACKUP"
        if [ $? -eq 0 ]; then
            log "INFO" "Backed up existing pip configuration to $PIP_CONFIG_BACKUP"
        else
            log "ERROR" "Failed to backup pip configuration"
            return 1
        fi
    fi
    return 0
}

# Update pip configuration to use Tsinghua mirror
update_pip_mirror() {
    setup_pip_directory || return 1
    backup_pip_config || return 1

    cat > "$PIP_CONFIG_FILE" << EOF
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn
EOF

    if [ $? -eq 0 ]; then
        log "INFO" "Successfully updated pip configuration to use Tsinghua mirror"
        # Test pip configuration
        if command -v pip3 >/dev/null 2>&1; then
            if pip3 config list 2>&1 | grep -q "index-url='https://pypi.tuna.tsinghua.edu.cn/simple'"; then
                log "INFO" "Pip configuration verified successfully"
            else
                log "WARNING" "Pip configuration might not be properly set"
            fi
        else
            log "WARNING" "pip3 not found, skipping configuration verification"
        fi
    else
        log "ERROR" "Failed to update pip configuration"
        # Restore backup if it exists
        if [ -f "$PIP_CONFIG_BACKUP" ]; then
            cp "$PIP_CONFIG_BACKUP" "$PIP_CONFIG_FILE"
            log "INFO" "Restored pip configuration backup"
        fi
        return 1
    fi
    return 0
}

main_update_apt_mirror() {
    log "INFO" "Starting mirror update script"
    check_root
    backup_sources
    detect_distribution
    generate_sources_content
    log "INFO" "Mirror update completed"
}

main_install_packages() {
    apt update
    apt install --yes python3 pip virtualenv clang antlr4
}

setup_compiler_env() {
    local script_dir=$1

    log "INFO" "Setting up venv"
    virtualenv "${script_dir}/../compiler/.venv"
    source "${script_dir}/../compiler/.venv/bin/activate"

    log "INFO" "Setting up uv"
    curl -LsSf https://astral.sh/uv/install.sh | sh
    (cd "${script_dir}/../compiler" && uv sync)

    log "INFO" "Generating antlr4 grammar"
    (cd "${script_dir}/../compiler" && ./generate-grammar)

    log "INFO" "Completed!"
    echo "Hint: run the following command to begin:"
    
    echo "  source ${script_dir}/../compiler/.venv/bin/activate"
    echo "  ${script_dir}/../compiler/run-test ${script_dir}/../test/ani_array -ani"
}

main() {
    script_dir=$(realpath "$(dirname "$0")")

    case "${1:-}" in
        update_apt_mirror)
            main_update_apt_mirror
            ;;
        install_pkg)
            main_install_packages
            ;;
        update_pip_mirror)
            update_pip_mirror
            ;;
        setup_compiler_env)
            setup_compiler_env "$script_dir"
            ;;
        *)
            sudo "$0" update_apt_mirror
            sudo "$0" install_pkg
            "$0" update_pip_mirror
            "$0" setup_compiler_env "$script_dir"
            ;;
    esac
}

# Set up trap for cleanup
trap cleanup EXIT

# Run main function
main "$@"

exit 0
